use std::collections::HashMap;
use std::sync::Mutex;
use crate::core::services::protocols::IContributionKeyword;
use super::types::ICommandHandler;

pub struct CommandsImplement {
    handlers: Mutex<HashMap<String, Box<dyn ICommandHandler>>>,
}

impl CommandsImplement {
    pub fn new() -> Self {
        Self {
            handlers: Mutex::new(HashMap::new()),
        }
    }

    pub fn register(&self, command_name: &str, handler: Box<dyn ICommandHandler>) {
        self.handlers.lock().unwrap().insert(command_name.to_string(), handler);
    }

    pub fn execute(&self, command_name: &str, args: std::sync::Arc<dyn std::any::Any + Send + Sync>) -> Result<std::sync::Arc<dyn std::any::Any + Send + Sync>, String> {
        if let Some(handler) = self.handlers.lock().unwrap().get(command_name) {
            handler.execute(args)
        } else {
            Err(format!("Command '{}' not found", command_name))
        }
    }
}

// This is the implementation for the `commands` keyword itself.
impl IContributionKeyword for CommandsImplement {
    fn init(&self, _options: crate::core::services::protocols::ContributionKeywordInitOptions) {}
    fn request_contribution(&self, _ctx: std::sync::Arc<dyn crate::core::services::protocols::IRequestContributionContext>, _definitions: &[crate::core::manifest::ContributeDefinition]) {}
    fn request_revoke_contribution(&self, _ctx: std::sync::Arc<dyn crate::core::services::protocols::IRequestContributionContext>, _definitions: &[crate::core::manifest::ContributeDefinition]) {}
    fn request_contribution_point(&self, _ctx: std::sync::Arc<dyn crate::core::services::protocols::IRequestContributionContext>, _definitions: &[crate::core::manifest::ContributionPointDefinition]) {}
    fn request_revoke_contribution_point(&self, _ctx: std::sync::Arc<dyn crate::core::services::protocols::IRequestContributionContext>, _definitions: &[crate::core::manifest::ContributionPointDefinition]) {}
    fn get_context(&self, _contributor: &str) -> Option<std::sync::Arc<dyn std::any::Any + Send + Sync>> { None }
    fn destructor(&self) {}
}